home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-04-12 | 62.0 KB | 1,639 lines |
- Path: bloom-beacon.mit.edu!hookup!news.moneng.mei.com!howland.reston.ans.net!EU.net!sunic!trane.uninett.no!nac.no!news.kth.se!hemul.nada.kth.se!d88-jwa
- From: d88-jwa@hemul.nada.kth.se (Jon WΣtte)
- Newsgroups: comp.sys.mac.programmer,comp.answers,news.answers
- Subject: The Mac Programming Public Domain FAQ Answer sheet.
- Followup-To: comp.sys.mac.programmer
- Date: 11 Apr 1994 09:13:50 GMT
- Organization: The Royal Institute of Technology
- Lines: 1621
- Approved: news-answers-request@MIT.Edu
- Expires: 1 May 94 00:00:00 GMT
- Message-ID: <2ob4ce$8l0@news.kth.se>
- NNTP-Posting-Host: hemul.nada.kth.se
- Mime-Version: 1.0
- Content-Type: text/plain; charset=iso-8859-1
- Content-Transfer-Encoding: 8bit
- Xref: bloom-beacon.mit.edu comp.sys.mac.programmer:44946 comp.answers:4851 news.answers:17895
-
- Archive-name: macintosh/programming-faq
-
- The Public Domain Mac Programming FAQ Answer sheet.
- Last update: 931023
-
- This sheet was started by and is presently maintained by Jon
- W{tte, whom you may reach as h+@nada.kth.se. If there is
- anything you find errant, missing or in need of an update,
- please send me your submission and I will include it (I can't
- promise correct attributions, but I will try) All FAQ Answer
- submissions sent to me will be considered to be in the public
- domain unless stated otherwise (in which case they will not be
- included in this FAQ sheet)
-
- This sheet is currently archived on nada.kth.se where you can
- reach it using afs as /afs/nada.kth.se/public/ftp/pub/hacks/mac-f
- aq/CSMP_PD_FAQ or using anonymous FTP (GIVE YOUR E-MAIL ADDRESS
- AS PASSWORD!) as pub/hacks/mac-faq/CSMP_PD_FAQ
-
- I will try to update this sheet every three weeks or so.
-
- This sheet is divided into several parts; each of which covers a
- general area which often gets asked about in the Internet
- newsgroup comp.sys.mac.programmer. Please download a copy of
- this answer sheet and search it before you post to the 'net, to
- help reduce bandwidth.
-
- There is NO or VERY LIMITED error checking in these code
- examples, FOR BREVITY ONLY. You should make sure you ALWAYS
- check ALL return codes, and handle any that you are not prepared
- to deal with appropriately.
-
- The coding style used in the example C code is my own, and
- you'll have to live with it.
-
- The groups are (you may search for *<number>* to jump directly
- to a group with its questions and answers)
-
- 0) Development and debugging tools and documentation for the Mac
- 1) Files and the File Manager
- 2) Serial ports
- 3) TCP/IP and sockets
- 4) AppleEvents and the Apple Object Model
- 5) AppleScript
- 6) Drawing using QuickDraw
- 7) Drawing NOT using QuickDraw (aka directly to screen)
- 8) Cache issues and other processor differences
- 9) What about pre-emptive multitasking?
- 10) Handles; they are driving me crazy; Memory issues
- 11) _Gestalt and compatibility
- 12) Standalone code and dynamic linking
- 13) Keyboard & Mouse for Games and Screen Savers
- 14) QuickTime
- 15) Windows, Menus, Dialogs
- 16) Ice Cream and Frozen Yoghurt
-
- *0* Development and debugging tools for the Macintosh
-
- 0.1) Q: What do I need to start writing Macintosh software?
-
- A: A Mac, a lot of time, and a few hundred $. Although you can
- develop software on a Classic-type machine, it is not to be
- attempted by the weak of heart or stressed of time. If you're
- doing paid work and/or work for a company, a Quadra-class
- machine or Centris 650 or better is almost a must; remember that
- your time costs your employer much more than just your salary. 8
- MB is a minimum to run at all comfortably, and Virtual Memory is
- not suited for development work. Similarly; if you don't have at
- least 20 MB free on your hard disk (40 MB for MPW) you need to
- buy more space.
-
- You need a development system such as Think C, CodeWarrior C++,
- MPW C or Prograph, you need at least some of the New Inside Mac
- books (Toolbox Essentials, Files, Memory come to mind) and a
- good entry-level third-party book may help.
-
- Once you are up to speed on the general layout of the Mac and
- its toolboxes, you should call APDA and order the monthly
- developer mailing, which will give you a CD chock full of
- documentation, utilities and system software once a month. You
- will also, obviously, need a CD player; one of which Apple's own
- CD300 is a very good buy at the time of writing this. If you
- don't have the dough for the monthly mailing ($250/year) you can
- order a _develop_ subscription; this quarterly magazine
- ($30-$50/year) comes with a CD containing all Inside Mac
- documentation.
-
- Another tool which many find a must-have is the Think Reference
- version 2.0.1, containing reference material on the most used
- parts of the Mac toolbox with lightning-fast look-up and mostly
- correct usage hints and code snippets.
-
- 0.2) Q: What is the most used Macintosh development language?
-
- A: Out of products on the market, I have no idea; both MPW and
- Think products appear to be used. Lately, CodeWarrior has come
- out of nowhere and grabbed a large share of the market
- visibility because they have the fastest compiler and they
- generate PowerPC code as well as 68K code. Among hobbyists, the
- Think products from Symantec are most popular because of the low
- price, and steep educational discounts, and, of course, the
- easily approachable interface!
-
- The Think C linker only strips dead code on a FILE level basis
- (and this is when you turn on "Smart Linking") The MPW linker
- (of no specified IQ, as someone so eloquently put it :-) strips
- dead code by the function, as does CodeWarrior. That may be part
- of the reason the Think C linker is ten times faster than the
- MPW linker.
-
- In the beginning, the Mac was programmed using Mc68000 assembly
- or Pascal; this was reflected in the Old Inside Mac volumes
- which only gave Pascal-style and assembly-style interfaces to
- the Mac toolbox. These days, Apple tells us to use C or even
- better C++ for developing new applications, as that will speed
- up the transition to PowerPC and also coming cross-platform
- efforts. (Language Systems have a Pascal for PowerPC product
- now, but I don't know about pricing or quality)
-
- There are also at least two Fortran compilers, at least three
- SmallTalk implementations (ObjectWorks, SmallTalk/V and
- SmallTalkAgents), a world-class LISP/CLOS implementation
- (Macintosh Common Lisp 2.0) and a Modula/2 implementation.
- Apparently, using Envy/packager, you can strip out unused code
- pretty effectively from Digitalk and PP apps, which are then
- smaller (and of course more memory efficient) than C++ apps.
-
- Metrowerks have a Pascal and a Modula II compiler. They're
- building C and C++ for both 68k and coming PPC Macs, and
- will also have a PowerPC Pascal.
-
- CSI has MacForth, of which I only know the name and someone who
- says it's pretty good.
-
- There is another good Common Lisp implementation: Procyon Common
- Lisp. I don't know if it is actively supported, but Procyon CL
- is also available for DOS, OS/2 and Windows (as Allegro CL/PC)
- and actively developed.
-
- 0.3) Q: Where do I find a public domain C compiler for the Mac.
- Is there a GCC for the mac? What about the FSF boycott of Apple
- products?
-
- A: There is no really good solution for a "for-free" C
- development system for the Mac. GCC has been ported, but
- requires the MPW shell and MPW assembler to run; these have to
- be bought from APDA. There is a standalone port of GCC 1.37 on
- nic.switch.ch:software/mac/src/think_c. There was a freely
- available C compiler called Harvest C, which was somewhat
- unstable but usable for smaller programs; it was abandoned by
- the original author Eric W Sink because of a lack of time and
- later taken up by the TopSoft project.
-
- The FSF boycott of Apple products means they will not talk to
- you if you ask them for help in doing a Mac port, and they will
- not incorporate your changes into their main code base. However,
- they still allow others to port GNU stuff to the Mac, and it has
- been done with most of the application-like GNU programs (bison,
- flex, perl (not really part of GNU), ...)
-
- gcc-1.37r14 V1.1 standalone is available for ftp at the address below.
-
- (A) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14.sit.bin
- (B) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14_src.sit.bin
- (C) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14_libsrc.sit.bin
- (D) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14_includes.sit.bin
-
- Exhibit (A) will be of interest to users who wish to play with an actual
- application. This can not be described as finished, but it is at least
- functional. Comments and feedback by e-mail to jrrk@camcon.co.uk are
- invited. Exhibit (B) will be of interest to those who like to tinker with
- source code and crib ideas for their own programs.
- Exhibit (C) will be useful to those who need a library to simplify porting
- of code from UNIX or who are otherwise fed up with the incompatabilities of
- the standard C library provided with THINK C. It is also needed to build
- (B) into a complete application, and also provides the basis of the object
- libraries supplied with (A).
- Exhibit (D) are the conventional (i.e. non mac toolbox) headers that are
- needed to compile the source code and for anyone who would like to write
- ANSI-C programs. However the number of hacks needed to gcc to make it
- support mac native toolbox applications is likely to make it unreliable as
- an ANSI compiler. For this purpose, I have found MacMiNT to be a better
- alternative.
-
- Highly recommended is to get the toolbox includes for MPW 3.2 and the
- 'spinside macintosh' hypercard stack from ftp.apple.com These will give
- users an idea of how to go about programming stand-alone Mac applications.
-
- 0.4) Q: Are there any other free Mac development platforms?
-
- A: Yerk and Mops. These are object oriented languages based on
- the old product Neon which itself was based on Forth. They are
- available with Manuals at oddjob.uchicago.edu (anonymous FTP).
-
- Plus, there's MacGambit, MacScheme, xlisp, and MacMETH which is
- the actual ETH (read: Nick Wirth's group) Modula 2, all for free
- via FTP.
-
- And OpenProlog. And SIOD (Scheme in One Defun) And [mail in more
- if you dare]
-
- 0.5) Q: What's the difference between the MPW and Think
- environments?
-
- A: The main difference is that Think is an integrated
- environment, while MPW provides you with a command-line shell
- for your Mac and tools to use in it. MPW also has a slightly
- higher systems demand and a much slower linker.
-
- The good thing about MPW is that you can write scripts and make
- files to do anything you want in the way you want it. Think
- still doesn't have a viable solution to do a build that requires
- more than one link operation, or has more than one destination
- file.
-
- For the MPW environment, there are three source level debuggers;
- SADE, SourceBug and Voodoo Monkey. The latter is an experimental
- debugger with support for threads debugging; the middle is
- bundled with MPW while SADE has to be bought separately (but is
- fully scriptable in its own scripting language)
-
- The Think environments have their own integrated debuggers; the
- Think Pascal one has a lot of useful features while the Think
- C/C++ one is a little more basic (but is gaining in
- functionality with each release) Stepping through source code
- and looking at variables is generally faster and easier in Think
- than the MPW debuggers.
-
- Any commercial Mac developer should have both Think and MPW of
- whatever language they prefer (Pascal, C or C++)
-
- 0.6) Q: What is a good low-level debugger for the Mac?
-
- A: MacsBug is freely available for ftp from ftp.apple.com; log
- in as user anonymous and give your FULL e-mail address as
- password. MacsBug is your basic monitor-type debugger that takes
- a few hundred Ks of memory, and lets you break, step,
- disassemble, look at the stack etc of most anything running on
- your Mac. Since it's free (it's also on the developer CDs) and
- provides most of the functionality you need, this is a popular
- choice.
-
- TMON is another debugger which sports a more mac-like interface;
- it provides windows and uses the mouse. It can take as little or
- much memory as you want by excluding or including certain areas
- of functionality. A nice touch is the 6502 disassembler that you
- can use to de-bug the code the IOP processors run on the Mac
- IIfx and Quadra 900/950.
-
- Jasik Designs have a debugger called The Debugger which can do
- both low- and high-level debugging, with or without source and
- for all types of code, application, code resources, everything.
- This is the debugger of choice for many large developers because
- of its high power and many features not found anywhere else.
- However; newcomers beware! This is the Lamborghini of debuggers;
- if you know how to drive it, it is the fastest way from A to B;
- if you don't, you'll just end up in the ditch. As a lady put it:
- "The man wouldn't know a user interface if it bit him in the
- rear."
-
- 0.7) Q: Are there any visual developments environments for the
- Mac (comparable to Visual C++)?
-
- A: There is no Visual C++ as such. However, there is a C++
- parser/editor called ObjectMaster which provides good browsing
- and editing capabilities if you already have a C++ compiler.
- Think C++ also comes with a browser built-in, and you can draw
- dialogs/windows using plain old ResEdit, even for your custom
- view types.
-
- AppMaker is a GUI builder/code generator. Granted, it's not as
- nice as VC++, but it's quite a product in any case.
-
- Also, Neuron Data has their UI tool called Open Interface, which
- is better than VC++ and creates code portable across 35
- platforms. Unfortunately it's $2500 per developer per platform.
- (There's also two other cross-platform products called XVT and
- Galaxy, the former has gotten flak on UseNet while the latter
- reportedly has decent networking support)
-
- There is a fully visual, dynamic, object oriented data-flow-drive
- n programming language for the Mac called Prograph Corporate
- Programming Something-or-other (CPX). It is expensive ($1500)
- but offers a built-in database, easy interfaces to existing data
- bases, very high productivity in implement-test-debug cycling
- and also offers cross-platform capabilities (it comes with a
- class library which, when your code is written using it, works
- under Windows after re-compilation)
-
- There is a crossing between SmallTalk and C++ that is called
- Component Workshop; although it seems large and slowly evolving,
- it does offer some promising features not found in C++ itself.
-
- There is also something called SmallTalkAgents that makes it
- easy to create Mac applications using SmallTalk. If you'd rather
- do Common Lisp, Macintosh Common Lisp offers a Common Lisp
- Object System with support for most Mac interface items; you can
- edit code while it is running and build stand-alone
- applications.
-
- However, all of these tools generate rather larger binaries with
- larger system demands than a program written in C. On the other
- hand; C++ programs require more memory and disk space than
- programs written in assembly. It's a trade-off, and I believe
- this type of tools is the wave of the near future.
-
- 0.8) Q: What class libraries are there for the Mac?
-
- A: Apart from the libraries mentioned above, there are three
- contenders: MacApp, TCL, and OOPC. On the horizon may be
- Bedrock.
-
- MacApp is a heavy-duty class library that has tons of features
- and a steep learning curve; it runs under MPW with Pascal or
- C++, and also under Think Pascal 4.0 A major application written
- in MacApp is PhotoShop.
-
- TCL stands for Think Class Library and comes with Think Pascal,
- C or C++. It is a smaller library that still fills most peoples
- needs; since Think C implements a subset of C++ (the most
- important OO concepts such as virtual functions and inheritance)
- and the TCL is carefully written not to take advantage of any
- C++ features not in Think C, you can use it with Think C. A
- major application written in TCL is Lotus 1-2-3.
-
- OOPC is a newcomer in the field, and uses plain ANSI C. However,
- it mangles the pre-processor to provide you with a system with
- full inheritance, virtual functions, and dynamic re-binding of
- functions for classes or individual objects. Start-up is slow,
- since all "linking" of virtual functions and classes is made at
- run-time, but performance otherwise is good. A Windows version
- is promised for later this year.
-
- 0.9) Q: How should I debug and test my software?
-
- A: Get ahold of, and install, the extensions DoubleTrouble,
- DisposeResource and EvenBetterBusError. They will catch 80% of
- any memory related bugs you may have, including many bugs that
- follow NULL handles or pointers.
-
- A low-level debugger is required, and while you install it,
- install the "leaks" dcmd which will help you catch memory leaks
- in your application. All of these tools are available from
- ftp.apple.com.
-
- *1* Files and the File Manager
-
- 1.1) Q: How do I tell fopen() to open a file the user has
- selected using StandardGetFile?
-
- A: The "standard" ANSI C file functions are less than well
- suited for the Macintosh way of doing things. However, if you
- are doing a port for your own enjoyment and benefit (or maybe
- for in-house work) you can use the following function: (see
- below about converting a wdRefNum into a vRefNum/parID pair)
-
- *code*
- FILE *
- fopen_mac ( short vRefNum , long parID , char * fileName , char * mode ) {
-
- short oldVol ;
- short aVol ;
- long aDir , aProc ;
- FILE * ret = NULL ;
-
- if ( GetVol ( NULL , & oldVol ) ) {
- return NULL ;
- }
- if ( GetWDInfo ( oldVol , & aVol , & aDir , & aProc ) ) {
- return NULL ;
- }
- if ( HSetVol ( NULL , vRefNum , parID ) ) {
- return NULL ;
- }
- ret = fopen ( fileName , mode ) ;
- if ( HSetVol ( aVol , aDir ) ) {
- /* an error we can't currently handle */
- }
- if ( SetVol ( oldVol ) ) {
- /* an error we can't currently handle */
- }
- return ret ;
- }
- *end*
-
- All of the above is necessary for one reason or another - if you
- are interested, by all means look HSetVol up in Think Reference
- 2.0 or New Inside Mac: Files.
-
- In older versions of MPW; this wouldn't work since the MPW
- libraries used to do a GetVol and explicitly use that value by
- itself.
-
- 1.2) Q: When can I use the HOpen, HCreate etc file calls? Are
- they only System 7 calls?
-
- A: All the HXxx calls that take a vRefNum and parID as well as
- the file name are implemented in glue that works on any system
- that has HFS (meaning 3.2 and up with the HD20 INIT, and all
- systems from System 6 and up)
-
- The glue is available in MPW 3.2 and up, and Think C 5.0 and up.
- This goes for all HXxx calls except HOpenDF; therefore, if you
- are interested in System 6 compatibility, use HOpen instead and
- make sure you don't allow file names beginning with a period.
-
- 1.3) Q: Why do you say wdRefNum sometimes and vRefNum sometimes?
- Why do you say parID sometimes and dirID sometimes?
-
- A: When the Mac first made an appearance in 1984, it identified
- files by using a vRefNum (volume reference number meaning a
- floppy disk or later hard disk) and a name. Once HFS saw the
- light of day, folders within folders became a reality, and you
- needed a dirID as well to point out what folder you really meant
- on the volume. However, older programs that wasn't being
- rewritten still knew nothing about directory IDs, so Apple had
- SFGetFile make up "fake" vRefNums that didn't just specify a
-
- volume, but also a parent folder. These are called wdRefNums
- (for working directory) and were a necessary evil invented in
- 1985. You should not create (or, indeed, use) wdRefNums
- yourself.
-
- There is a system-wide table that maps wdRefNums onto
- vRefNum/parID pairs. There is a limit to the size of this table.
- A dirID and a parID is almost the same thing; you say "parID"
- when you mean the folder something is in, while you say a
- "dirID" when you mean the folder itself. If you for instance
- have a folder called "Foo" with a folder called "Bar" in it, the
- parID for "Bar" would be the dirID for "Foo."
-
- 1.4) Q: How do I convert a wdRefNum as returned by SFGetFile
- into a vRefNum/parID pair to use with the HXxx calls.
-
- A: Use GetWDInfo, which is declared as:
-
- Pascal OSErr GetWDInfo ( short wdRefNum , short * vRefNum , long
- * parID , OSType * procID ) ;
-
- The procID parameter must be non-NULL and point to an OSType
- variable, but the value of that variable can and should be
- ignored.
-
- It is recommended that, as soon as you get your hands on a
- wdRefNum, for instance from SFGetFile, you directly convert it
- into a vRefNum/parID pair and always use the latter to reference
- the folder.
-
- 1.5) Q: How do I select a folder using SFGetFile?
-
- A: This requires a custom dialog with a filter proc. It is too
- complicated to show here, but not totally impossible to
- comprehend. There is sample code on ftp.apple.com, in the
- directory dts/snippets, on how to do this.
-
- 1.6) Q: How do I get the full path of a file referenced by a
- vRefNum, parID and name?
-
- A: You don't.
-
- OK, I cheated you. There is exactly ONE valid reason to get the
- full path of a file (or folder, for that matter) and that is to
- display its location to the user in, say, a settings dialog. To
- actually save the location of the file you should do this:
- (assuming the file is in an FSSpec called theFile - you can use
- FSSpecs in your program even if you don't run under System 7;
- just make your own MyFSMakeFSSpec that fills in the FSSpec
- manually if it's not implemented)
-
- *code*
- if ( ! aliasManagerAvailable ) { /* System 6 ? */
- GetVolumeName ( theFile -> vRefNum , vName ) ;
- GetVolumeModDate ( vRefNum , & date ) ;
- Save ( vName , date , parID , fileName ) ;
- } else {
- NewAlias ( NULL , theFile , & theAlias ) ;
- Save ( theAlias ) ;
- DisposeHandle ( ( Handle ) theAlias ) ;
- }
- *end*
-
- If you are really concerned about these issues (of course you
- are!) you should save BOTH of these methods when available, and
- load back whatever is there that you can handle; since users may
- be using your application in a mixed System 6/System 7
- environment.
-
- To get back to the file is left as an exercise for the reader.
-
- To open a file using fopen() or the Pascal equivalent, see above
- about using and not using HSetVol.
-
- 1.7) Q: What about actually getting the full path for a file? I
- promise I will only use it to show the location of a file to the
- user!
-
- A: Enter PBGetCatInfo, the Vegimatic of the Mac file system. Any
- Mac hacker of knowledge has taken this system call to his heart.
- What you do is this:
-
- *code*
- OSErr
- GetFolderParent ( FSSpec * fss , FSSpec * parent ) {
-
- CInfoPBRec rec ;
- short err ;
-
- * parent = * fss ;
- rec . hFileInfo . ioNamePtr = parent -> name ;
- rec . hFileInfo . ioVRefNum = parent -> vRefNum ;
- rec . hFileInfo . ioDirID = parent -> parID ;
- if ( parent -> name [ 0 ] ) {
- rec . hFileInfo . ioFDirIndex = 0 ;
- } else {
- rec . hFileInfo . ioFDirIndex = -1 ;
- }
- rec . hFileInfo . ioFVersNum = 0 ;
- err = PBGetCatInfoSync ( & rec ) ;
- if ( ! ( rec . hFileInfo . ioFlAttrib & 0x10 ) ) { /* Not a folder */
- if ( ! err ) {
- err = dirNFErr ;
- }
- } else {
- parent -> parID = rec . dirInfo . ioDrParID ;
- parent -> name [ 0 ] = 0 ;
- }
- return err ;
- }
-
-
- OSErr
- GetFullPathHandle ( FSSpec * fss , Handle * h ) {
-
- Handle tempH = NULL ;
- short err ;
- FSSpec fs = * fss ;
-
- while ( fs . parID > 1 ) {
- tempH = NULL ;
- PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
- PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
- HandAndHand ( * h , tempH ) ;
- SetHandleSize ( * h , 0L ) ;
- HandAndHand ( tempH , * h ) ;
- DisposeHandle ( tempH ) ;
- tempH = NULL ;
- GetFolderParent ( & fs , & sSpec ) ;
- fs = sSpec ;
- }
- GetVolName ( fs . vRefNum , fs . name ) ;
- PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
- PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
- HandAndHand ( * h , tempH ) ;
- SetHandleSize ( * h , 0L ) ;
- HandAndHand ( tempH , * h ) ;
- DisposeHandle ( tempH ) ;
- tempH = NULL ;
- if ( ! IsFolder ( fss ) ) {
- SetHandleSize ( * h , GetHandleSize ( * h ) - 1 ) ; // Remove colon }
- return 0 ;
- }
- *end*
-
- 1.8) Q: So how do I get the names of the files in a directory?
-
- A: You use PBGetCatInfo again, but this time you set ioFDirIndex
- to 1 or more (you need to know the dirID and vRefNum of the
-
- folder you're interested in) You then call PBGetCatInfoSync for
- values of ioFDirIndex from 1 and up, until you get an fnfErr.
- Any other err means you are not allowed to get info about THAT
- item, but you may be for the next. Then collect the names in the
- string you made ioNamePtr point to as you go along. Note that
- you need to fill in the ioDirID field for each iteration through
- the loop, and preferrably clear the ioFVersNum as well.
-
- Note that the contents of a directory may very well change while
- you are iterating over it; this is most likely on a file server
- that more than one user uses, or under System 7 where you run
- Personal File Share.
-
- 1.9) Q: How do I find the name of a folder for which I only know
- the dirID and vRefNum?
-
- A: You call (surprise!) PBGetCatInfo! Make ioNamePtr point to an
- empty string (but NOT NULL) of length 63 (like, an Str63) and
- ioFDirIndex negative (-1 is a given winner) - this makes
- PBGetCatInfo return information about the vRefNum/dirID folder
- instead of the file/folder specified by vRefNum, parID and name.
-
- 1.10) Q: How do I make the Finder see a new file that I created?
- Or if I changed the type of it; how do I display a new icon for
- it?
-
- A: You call (surprise!) PBGetCatInfo followed by PBSetCatInfo
- for the FOLDER the file is in. Inbetween, you should set
- ioDrMdDat to the current date&time. Code:
-
- *code*
- OSErr
- TouchFolder ( short vRefNum , long parID ) {
-
- CInfoPBRec rec ;
- Str63 name ;
- short err ;
-
- rec . hFileInfo . ioNamePtr = name ;
- name [ 0 ] = 0 ;
- rec . hFileInfo . ioVRefNum = vRefNum ;
- rec . hFileInfo . ioDirID = parID ;
- rec . hFileInfo . ioFDirIndex = -1 ;
- rec . hFileInfo . ioFVersNum = 0 ;
- err = PBGetCatInfoSync ( & rec ) ;
- if ( err ) {
- return err ;
- }
- GetDateTime ( & rec . dirInfo . ioDrMdDat ) ;
- rec . hFileInfo . ioVRefNum = vRefNum ;
- rec . hFileInfo . ioDirID = parID ;
- rec . hFileInfo . ioFDirIndex = -1 ;
- rec . hFileInfo . ioFVersNum = 0 ;
- rec . hFileInfo . ioNamePtr [ 0 ] = 0 ;
- err = PBSetCatInfoSync ( & rec ) ;
- return err ;
- }
- *end*
-
- 1.11) Q: Aren't we done with PBGetCatInfo soon?
-
- A: Well, it turns out that you can also find out whether an
- FSSpec is a file or a folder by calling PBGetCatInfo and check
- bit 4 (0x10) of ioFlAttr to see whether it is a folder. You may
- prefer to call ResolveAliasFile for this instead.
-
- You can also check the script of the file's title using
- PBGetCatInfo and check the ioFlFndrXInfo field if you want to
- work with other script systems than the Roman system.
-
- Another common use is to find out how many items are in a
- folder; the modification date of something or the correct
- capitalization of its name (since the Mac file system is case
- independent BUT preserves the case the user uses)
-
- 1.12) Q: How do I set what folder should initially be shown in
- the SFGetFile boxes?
-
- A: You stuff the dirID you want to show into the lo-mem global
- CurDirStore, and the NEGATIVE of the vRefNum you want into the
- lo-mem global SFSaveDisk.
-
- If you are using CustomGetFile and return sfSelectionChanged
- from an "init" message handler, you must remember to clear the
- script code, else the selection will not change.
-
- 1.13) Q: How do I find the folder my application started from?
- How do I find the application file that's running?
-
- A: Under System 7, you call GetCurrentProcess, followed by
- GetProcessInformation with a pointer to an existing FSSpec in
- the parameter block. This will give you your file, and, by using
- the vRefNum and parID, the folder the application is in.
-
- Beware from writing to your applications resource or data forks;
- the former breaks on CDs/write protected floppies/file
- servers/virus checkers, the latter fails on PowerPC as well as
- in the above cases.
-
- *2* Serial ports
-
- 2.1) Q: How do I get at the serial ports?
-
- A: You call OpenDriver for the names "\p.AOut" and "\p.AIn" to
- get at the modem port, and "\p.BOut" and "\p.BIn" for the
- printer port. The function RAMSDOpen was designed for the
- original Mac with 128 kB of memory and 64 kB of ROM, and has
- been extinct for several years.
-
- However, many users use their serial ports for MIDI, LocalTalk,
- graphic tablets, or what have you and have installed an
- additional serial port card to get more ports. What you SHOULD
- do as a good application is to use the Comms Toolbox Resource
- Manager to search for serial resources; this requires that the
- Comms Toolbox is present (true on earlier System 6 with an INIT,
- on later System 6 and System 7 always, as well as on A/UX) and
- that you have initialized the comms resource manager. The exact
- code follows (adapted from Inside Mac Comms Toolbox):
-
- *code*
- #include <CommsResources.h>
- OSErr
- FindPorts ( Handle * portOutNames , Handle * portInNames , Handle * names , Handle * iconHandles ) {
-
- OSErr ret = noErr ;
- short old = 0 ;
- CRMRec theCRMRec , * found ;
- CRMSerialRecord * serial ;
-
- * portOutNames = NewHandle ( 0L ) ;
- * portInNames = NewHandle ( 0L ) ;
- * names = NewHandle ( 0L ) ;
- * iconHandles = NewHandle ( 0L ) ;
- while ( ! ret ) {
- theCRMRec . crmDeviceType = crmSerialDevice ;
- theCRMRec . crmDeviceID = old ;
- found = ( CRMRec * ) CRMSearch ( ( QElementPtr ) & theCRMRec ) ;
- if ( found ) {
- serial = ( CRMSerialRecord * ) found -> crmAttributes ;
- old = found -> crmDeviceID ;
- PtrAndHand ( & serial -> outputDriverName , * portOutNames ,
- sizeof ( serial -> outputDriverName ) ) ;
- PtrAndHand ( & serial -> inputDriverName , * portInNames ,
- sizeof ( serial -> inputDriverName ) ) ;
- PtrAndHand ( & serial -> name , * names ,
- sizeof ( serial -> name ) ) ;
- PtrAndHand ( & serial -> deviceIcon , * iconHandles ,
- sizeof ( serial -> deviceIcon ) ) ;
- } else {
- break ;
- }
- }
- return err ;
- }
- *end*
-
- This will create four handles with the driver names, device
- names and driver icon handles for all of the available serial
- devices. Then let the user choose with a pop-up menu or
- scrolling list, and save the choice in your settings file.
-
- You can use OpenDriver, SetReset, SetHShake, SetSetBuf,
- SerGetBuf and the other Serial Manager functions on these
- drivers. To write to the serial port, use FSWrite for
- synchronous writes that wait until all is written, or PBWrite
- asynchronously for queuing up data that is supposed to go out
- but you don't want to wait for it. At least once each tim
-
- e through your event loop, you should call SerGetBuf on the in
- driver reference number you got from OpenDriver, and call FSRead
- for that many bytes - neither more nor less.
-
- If you are REALLY interested in doing the right thing, you will
- use the Communications Toolbox Connection Manager instead; this
- will give you access to modems, direct lines, and networks of
- various kinds using the same API! Great for stuff like BBSes
- that may be on a network as well etc. The Comms Toolbox also
- priovides modularized terminal emulat
-
- ion and file transfer tools, although the Apple-suplied VT102
- tool is pretty lame, as is the VT102 mode of the VT320 tool.
-
- *3* TCP/IP and sockets
-
- 3.1) Q: Where is a Berkley sockets library for the Mac?
-
- A: There are some problems with that. MacTCP, the Mac Toolbox
- implementation of TCP/IP, doesn't have an API that looks at all
- like Berkley sockets. For instance, there is ONE paramater-block
- call to do a combined listen()/accept()/bind() - sort of. I have
- heard that there may be a socket library available by ftp from
- MIT but haven't seen it myself.
-
- There is also a pretty good C++ TCP implementation called GUSI
- which is easily handled, and it also is callable from C using
- the Berkley socket API. Apart from TCP, it also handles
- "standard" Mac network protocols such as ADSP. The big
- disadvantage is that it is currently only implemented for MPW.
- The ftp site is nic.switch.ch, software/mac/src/mpw_c.
-
- I can also recommend the Communications Toolbox; for the price
- of using an API that is simpler than the Berkley sockets, you
- get the benefit of being able to use any kind of connection (TCP
- tools are available)
-
- Novell and Wollogong offer commercial socket-like libraries.
-
- 3.2) Q: Where do I find MacTCP?
-
- A: You can buy the MacTCP developers kit from APDA. It is also
- available on E T O, and if you want saner headers than those,
- try ftp to seeding.apple.com.
-
- *4* AppleEvents and the AppleEvent Object Model
-
- 4.1) Q: What are AppleEvents?
-
- A: AppleEvents are a level-5 network protocol. If you are not
- familiar with the ISO network stack, this means it's a way of
- structuring sessions between network entities (programs) that is
- not dependent on the underlying protocol (such as PPC or TCP/IP)
- Despite being a network protocol, they can be very useful on
- Macs that are not on a network. In short, they provide
- applications with a comprehensive way to send arbitrary
- structured data to other applications (or themselves) which
- receive the events through their main event loop.
-
- The AppleEvent Object Model is a way of looking at applications
- and the data they contain, and also a level-6 network protocol.
- You _can_ send AppleEvent Object Model data through AppleEvents
- (and the standard AppleEvents defined in the AppleEvent Registry
- use it) but you don't have to - unless you want to talk with
- other applications, of course, then the AEOM is a lingua franca.
- 4.2) Q: What are the four required AppleEvents?
-
- A: There are four events your application really must implement
- if you want to sell it: the kCoreEventClass class,
- kAEOpenApplication, kAEQuitApplication, kAEOpenDocuments and
- kAEPrintDocuments events IDs. When you support these events (or
- any AppleEvents) you will not get startup info through
- GetAppParams() anymore, unless you run under System 6 of course.
- The kAEOpenApplication event will be sent to you when the user
- double-clicks your app and it's not started yet. When receiving
- it, you can put up a new untitled window.
-
- kAEOpenDocuments is sent when the user double-clicks your apps
- documents. Note that if the first AppleEvent you receive is a
- kAEOpenDocuments event, the user started your app by
- double-clicking its documents.
-
- kAEPrintDocuments is sent when the user selects your documents
- and chooses "Print" in the Finder menu. If this is the first
- AppleEvent you receive, you should print the documents and then
- quit the application again; if you received a kAEOpenApplication
- or kAEOpenDocuments event before this, you should just print the
- documents and close them when you're done.
-
- kAEQuitApplication is sent to you when the user chooses
- "Shutdown" or "Restart" from the Apple Menu. You should ask the
- user whether he wants to save any unsaved changed documents, and
- then quit unless the user presses Cancel.
-
- Interestingly enough, you can use these four AppleEvents to send
- even to non-AE-aware applications, and the system will translate
- these events into fake menu selections for you.
-
- A good way of shutting down the Finder is to send it a Quit
- AppleEvent. You should send a Quit AppleEvent to File Sharing
- Extension before you shut down the Finder, though; the FSE is
- found by looking for a process with the creator 'hhgg'.
-
- 4.3) Q: Are there any limits or tradeoffs with AppleEvents?
-
- A: As always, more power means more responsibility.
-
- AppleEvents sent to applications on other Macs require
- authentification the first time they are sent. If the remote Mac
- allows Guests to link to programs, the INIT AutoGuest 2.0 might
- help (or the code solution that comes with it and you can build
- into your application)
-
- In the first version of the AppleEvent manager, there was a
- total 64K limit on the size of data and overhead. This limit has
- been lifted with the version of the AppleEvent manager that
- comes with AppleScript.
-
- AppleEvents require a lot of memory copying and handle resizing
- in their construction; this means that large AppleEvents may be
- slow in construction, especially when compared to a pure PPC
- Toolbox or ADSP/ASDSP link.
-
- You should use your own application signature as event class for
- AppleEvents you make up, in order not to collide with anybody
- else. Other than that, you are free to make your own events for
- your own needs, though supporting the required events and at
- least a subset of the Core event suite will buy you a lot of
- functinality from within AppleScript. Especially important are
- the Get Current Selection and Set Current Selection events
- (which are really Get/Set Data on the contents of the current
- selection of the application)
-
- The signature for your application SHOULD be registered with DTS
- to avoid conflicts; this is done through e-mail to
- DEVSUPPORT@AppleLink.Apple.Com and the form you use is located
- on the developer CDs and found on ftp.apple.com.
-
- *5* AppleScript
-
- 5.1) Q: How does AppleEvents interface with AppleScript?
-
- A: AppleEvents are the meat and potatoes of AppleScript. If you
- support the AppleEvent Object Model from within your
- application, users can control you through AppleScript.
-
- The first thing you should do is get ahold of Inside Mac:
- Interapplication Communication, and a copy of the AppleEvents
- Registry. The former tells you all you ever need to know about
- AppleEvents, while the latter is paramount for implementing the
- right standard events. If everybody use the standard events,
- dynamic data interchange between any applications will become
- sweet reality!
-
- Then there is the 'aete' resource which lets you put names on
- the events you support, so that users can "Open Terminology" on
- your application from within the Apple Script Editor and use the
- proper AppleScript commands in their scripts. The format of an
- aete resource is defined in Inside Macintosh: Interapplication
- Communication.
-
- 5.2) Q: Can I compile and run scripts from within my
- application?
-
- A: Yes, this is very simple. There are toolbox calls for reading
- scripts, compiling scripts, and executing scripts. (OSACompile,
- OSAExecute) These are all documented in Inside Mac:
- Interapplication Communication.
-
- 5.3) Q: Is this a good way of getting a macro language almost
- for free?
-
- A: "Good" is an understatement. Just let users write scripts,
- load them into menu items and go. Total systems integration in
- under a week, including adding support for the AEOM to your
- application.
-
- There is source code for an application called "MenuScipter" on
- the developer CD which shows you how to do an application with
- all of the menus being AppleScript scripts.
-
- *6* Drawing using QuickDraw
-
- 6.1) Q: Why is CopyBits so slow?
-
- A: It is not. It just requires some hand-holding to get good
- results. The main rules are: Make sure the source and
- destination pixMaps are of the same depth.
-
- Make sure the front color is black and the back color is white.
-
- Use srcCopy and don't use a masking region.
-
- Copy to an unclipped window (the frontmost window).
-
- Make sure the ctSeed values of the source pixMap and dest pixMap
- match.
-
- Copying few and large pixMaps is faster than copying many and
- small ones. Icon-sized sprites count as small ones.
-
- Make sure your source bitmap or pixelMap has the same alignment,
- when adjusted for the source and destination rect expressed in
- global screen coordinates. The necessary alignment is 32 bits (4
- bytes), although 128 bit (16 byte) alignment is probably even
- better on 68040 macs and won't hurt on other macs.
-
- Example of global alignment:
-
- Your window is positioned at (42,100) (H,V)
-
- Your destination rectangle is (10,20)-(74,52)
-
- The alignment coefficient of the rectangle in global coordinates
- is (42+10)*bitDepth where bitDepth is one of 1,2,4,8,16 or 32.
-
- Make sure your source pixmap rect has the same coeffecient
- modulo your alignment factor (in bits) For black&white macs,
- this is still true, although bitDepth is fix at 1. Offscreen
- pixMaps can calculate with a "global posistion" of 0,0 and get
- correct results.
-
- 6.2) Q: Why is CopyBits still too slow?
-
- A: Because there is always some overhead involved in calling
- QuickDraw; you have the trap dispatcher, clipping checks, and
- checking whether the CopyBits call is being recorded in a PICT
- handle (if you called OpenPicture)
-
- If you can't live with this, look at *7* below, but PLEASE try
- and make CopyBits work, and retain the CopyBits code in your
- application, so users with special monitors (accellerator cards,
- PowerBook color screens, Radius Pivot screens) can still play
- your game. (non-game applications don't need more speed than
- CopyBits can give at its max. Promise!)
-
- 6.3) Q: What is the fastest way to set one pixel?
-
- A: NOT SetCPixel()! Assuming you have the correct ForeColor()
- set, you can set the pen size to (1,0) and call Line (0,1)
-
- I have heard PaintRect is good for this but requires slightly
- more code. Using PaintRect eliminates a trap call.
-
- 6.4) Q: Why do pictures I record suddenly draw as empty space or
- not draw at all?
-
- A: When recording pictures, you have to set the clipping area to
- exactly the frame of the picture you are recording. This is
- because it is initally set at -32768,32727 in both directions,
- and offsetting the picture even one pixel when drawing it will
- result in the region wrapping around and becoming empty.
-
- When recording pictures, do this:
-
- *code*
- PicHandle h = OpenPicture ( & theRect ) ;
- ClipRect ( & theRect ) ;
- /* draw the picture */
- ClosePicture ( ) ;
- *end*
-
- 6.5) Q: Where can I find the format of picture files and
- resources?
-
- A: The format of a picture resource version 1 is defined in a
- technical note. This format is obsolete.
-
- The format of a picture resource version 2 is defined in Old
- Inside Mac vol V, with addenda in Old Inside Mac vol VI.
-
- Some things happen with QuickTime compressed pictures; try the
- Inside Mac: QuickTime book or wait for Inside Mac: Imaging which
- is the definite reference on QuickDraw.
-
- The format of a picture file is the same as that of a picture
- resource with 512 added 0 bytes in front.
-
- 6.6) Q: GWorlds?
-
- A: What about them? They're great. Look them up in Old Inside
- Mac vol VI. Don't forget to SetGWorld back to what it was before
- calling WaitNextEvent.
-
- 6.7) Q: How do I find the current depth of the screen?
-
- A: My question to you is: What screen? Many macs have more than
- one screen attached. You can use GetDeviceList and walk the
- devices to find the screen you're looking for (use
- TestDeviceAttrib to see whether it's a screen) or you can call
- GetMaxDevice() to find the deepest device your window
- intersects.
-
- Once you have the device handle, finding the depth is just a
- matter of looking at the dgPMap pixMapHandle, and dereference it
- to the pmSize field. Done.
-
- *7* Drawing directly to screen
-
- 7.1) Q: Why is it a bad idea to draw directly to screen?
-
- A: Because of several reasons:
-
- - You will be incompatible with future display hardware.
-
- - You will be incompatible with some present-day display
- hardware, such as Radius Pivots and PowerBook color screens.
-
- - You have to think about a lot of things; testing it all on
- your own machine is not possible and the chances of crashing are
- great.
-
- - You will be incompatible with future hardware where devices
- may live in some unaccessible I/O space.
-
- 7.2) Q: But I really need to do it. I can't make my animation
- into a QuickTime movie, and CopyBits is too slow, even when
- syncing to the screen retrace.
-
- A: You have to prepare yourself, and ask these questions:
-
- 1) Do I want to support all screens, or just 8-bit devices?
-
- 2) Do I have a few weeks of free time to make it work?
-
- 3) Do I want to get nasty mail when I break on some hardware and
- have to rev the application - even if I may not be able to get
- ahold of the hardware that makes it break?
-
- If all you're doing is rendering an image pixel-by-pixel or
- line-by-line, maybe you can draw directly into an offscreen
- pixMap/GWorld and then CopyBits the entire GWorld to screen?
- That will be more compatible, especially if you use the
- keepLocal flag when creating the GWorld.
-
- 7.3) Q: Okay, so how do I get the base address of the screen?
-
- A: "The" screen? Which screen? There may be several. The base
- address may be on an accellerated screen card. There may be more
- than one screen covering the same desktop area.
-
- Due to unfortunate circumstances, there is a bug in
- GetPixBaseAddr() that causes it to return incorrect results for
- some versions of System 7. Instead, get the baseAddr directly
- from the gdPMap handle of the GDHandle for the screen you draw
- to. This address may need switching to 32bit mode to be valid.
-
- 7.4) Q: Quit stalling and give me code!
-
- A: Okay, but I'll let you sweat over Inside Mac to figure out
- what it does. All of it is important; believe me! To make this
- code run faster, a lot of the things it does can be done once
- before starting to draw.
-
- Make sure that you have a window that covers the area where you
- are drawing, so other windows will not be overdrawn. Also make
- sure that you do not do direct-to-screen-drawing while you are
- in the background.
-
- *code*
- /* This is presently untested code */
- /* Value is dependent on what depth the screen has */
- /* This code doesn't work on non-color-quickdraw Macs (i e the MacClassic) */
- /* "where" is in GLOBAL coordinates */
- void
- SetPixel ( Point where , unsigned long value ) {
-
- Rect r ;
- GDHandle theGD ;
- char * ptr ;
- long rowBytes ;
- short bitsPerPixel ;
- PixMapHandle pmh ;
- Boolean oldMode ;
-
- r . left = where . h ;
- r . top = where . v ;
- r . right = r . left + 1 ;
- r . bottom = r . top + 1 ;
- theGD = GetMaxDevice ( & r ) ;
- if ( theGD ) {
- where . v -= ( * theGD ) -> gdRect . left ;
- where . h -= ( * theGD ) -> gdRect . top ;
- pmh = ( * theGD ) -> gdPMap ;
- rowBytes = ( ( * pmh ) -> rowBytes ) & 0x3fff ;
- ptr = ( char * ) ( * pmh ) -> baseAddr ;
- bitsPerPixel = ( * pmh ) -> pixelSize ;
- oldMode = true32b ;
- ptr += where . v * rowBytes ;
- SwapMMUMode ( & oldMode ) ;
- switch ( bitsPerPixel ) {
- case 1 :
- if ( value & 1 ) {
- ptr [ where . h >> 3 ] |= ( 128 >> ( where . h & 7 ) ) ;
- } else {
- ptr [ where . h >> 3 ] &= ~( 128 >> ( where . h & 7 ) ) ;
- }
- break ;
- case 2 :
- ptr [ where . h >> 2 ] &= ( 192 >> 2 * ( where . h & 3 ) ) ;
- ptr [ where . h >> 2 ] |= ( value & 3 ) << 2 * ( 3 - ( where . h & 3 ) ) ;
- break ;
- case 4 :
- ptr [ where . h >> 1 ] &= ( where . h & 1 ) ? 0xf : 0xf0 ;
- ptr [ where . h >> 1 ] |= ( value & 15 ) << 4 * ( 1 - ( where . h & 1 ) ) ;
- break ;
- case 8 :
- ptr [ where . h ] = value ;
- break ;
- case 16 :
- ( ( unsigned short * ) ptr ) [ where . h ] = value ;
- break ;
- case 32 :
- ( ( unsigned long * ) ptr ) [ where . h ] = value ;
- break ;
- default :
- abort ( ) ; /* Should never get here */
- }
- SwapMMUMode ( & oldMode ) ;
- }
- }
- *end*
-
- *8* Cache issues and other processor differences
-
- 8.1) Q: Why does my application work on an SE with accellerator
- (or a Mac II or Quadra), but not on one without?
-
- A: Assuming you're not calling Color QuickDraw (which is not
- available on accellerated SEs), you most probably have an
- odd-aligned word access somewhere.
-
- The 68000 does not allow words or longwords to be read from odd
- addresses, while the 68020 and up relaxes this restriction (it
- still is slower than aligned-word access though)
-
- This may or may not crash depending on your compiler:
-
- *code*
- struct foo {
- char c1 ;
- char c2 ;
- char c3 ;
- char c4 ;
- char c5 ;
- } bar ;
-
- long * x = ( long * ) & bar . c2 ;
- * x = 0x12345678 ; /* X is odd if compiler doesn't pad */
-
- This WILL crash on an SE/Plus/Classic/PB100:
-
- char foo [ 10 ] ;
-
- long * x = ( long * ) & foo [ 1 ] ;
- * x = 0x12345678 ;
-
- *end*
-
- 8.2) Q: Why does my application work on a IIci but not on a
- Quadra?
-
- A: Two reasons:
-
- 1) The Quadras 900 and 950 have special processors that handle
- the serial ports; if you write directly to the serial chips, you
- will crash (this goes for the IIfx as well)
-
- 2) The Quadras have 68040 processors, as have the Centrises.
- These processors have separate instruction and data caches (like
- the 68030) but they are larger (4K each) and unlike the 68030
- which is write-through data cached, the 68040 is copy-back data
- cached. This means that changes you make to "your code" aren't
- really changed all the time, since the changes may still be in
- the data cache and not written to memory when the CPU reads that
- part of memory into its I-cache. Even worse; that part might
- already have been read into the I-cache before you change it in
- the D-cache, meaning that writing out the D-cache will still not
- be enough. You need to flush both the caches when writing
- self-modifying code.
-
- Self-modifying code includes code that builds its own jump
- tables and code that decrypts itself and code that "stubs" MDEFs
- or WDEFs to jump back into the application code.
-
- You flush the cache using FlushDataCache() which is implemented
- if Gestalt says you have a 68020 or better processor (or if the
- _HwDispatch trap is implemented)
-
- 8.3) Q: Why does my application work on my Quadra but not on my
- accellerated SE?
-
- A: You're probably calling Color QuickDraw without first
- checking if it's available. The following machines do not have
- color QuickDraw in ROM nor RAM:
-
- Mac Plus, Mac SE, Mac Classic, Mac Luggable, PowerBook 100,
- Outbound
-
- 8.4) Q: I do check for color quickdraw, but crash nevertheless.
-
- A: _Gestalt lies under some versions of System 7; it says that
- non-color machines HAVE color QuickDraw when you test using the
- gestaltQuickdrawFeatures selector.
-
- Instead, check the gestaltQuickdrawVersion selector, if it
- returns >= gestalt8BitQuickdraw then you can safely use
- gestaltQuickdrawFeatures, else you only have b/w QuickDraw.
-
- 8.5) Q: Why are there no C/C++ compilers that optimize for the
- Mc68040?
-
- A: Beats me; optimizing for the 68040 can make programs up to
- 50% faster on that chip while still losing nothing, or very
- little (less than 10%) on older chips.
-
- *9* Inflammatory subjects
-
- 9.1) Q: What about pre-emptive multitasking?
-
- A: To the user, the Mac multitasking method, which builds upon
- each application calling WaitNextEvent, GetNextEvent or
- EventAvail every so often and the Process Manager/MultiFinder
- switching applications only at such calls, is at least as good
- as preemtive multitasking, because the present system
- priotitizes user interface responsiveness over everything else.
- The only shortfall about this is formatting floppies, which
- locks up the Mac CPU. This is because the Mac floppy controller
- is really stupid, and would happen even if the Mac multitasked
- preemptively.
-
- There IS "real" pre-emptive multitasking available for use in
- Mac applications; the expensive way is buying A/UX 3.0 which can
- have Mac applications written as UNIX processes; the cheap way
- is installing the Thread Manager which will allow you to create
- pre-emptive threads. However, the restrictions on those threads
- are the same as those on Time Manager tasks: don't call any
- function in an unloaded segment, and don't call QuickDraw or any
- toolbox call which may move memory (which are most ToolBox
- calls; paradoxally, BlockMove is safe :-) as are, surprisingly,
- FSRead and FSWrite)
-
- There are several problems with making the Mac OS preemptive;
- including apps that draw outside their windows or directly to
- screen, user dragging and other issues.
-
- 9.2) Q: What about protected memory? I'm sick and tired of
- re-booting when my application crashes.
-
- A: Write better software!
-
- Or install The Debugger from Jasik Designs, which can provide
- your application with write-protection of critical parts of
- memory. This may only work for 030 Macs, though.
-
- Making the Mac OS memory-protected is tricky, because
- applications expect to be able to write to low memory, the
- system heap, temporary memory, window lists, and even each
- other's heaps in some interapplication communication solutions
- that date back to before AppleEvents and the PPC Toolbox.
-
- *10* Handles; they are driving me crazy
-
- 10.1) Q: What is a handle?
-
- A: A handle is a pointer to a pointer to something. However, it
- is more than that; creating a handle by taking the address of
- one of your own pointers does NOT create a Handle; the Memory
- Manager will only deal properly with Handles that are created
- using NewHandle or something that calls it (such as NewRgn or
- GetResource)
-
- 10.2) Q: When do I have to lock a Handle?
-
- A: The contents of a Handle may move, and when it does, the
- pointer your handle is pointing to is changed to point to the
- new address so your handle is always valid. The toolbox may call
- the memory manager to allocate more memory pretty much anytime
-
- you call it (the toolbox) and when memory is allocated, your
- handle may move in memory. Don't dereference a handle into a
- pointer (or take the address of a field in a record a handle is
- double-pointing to) and then call the toolbox and expect the
- pointer to still be valid. The only way to ensure that the
- pointer will still be valid is to call HLock on the handle to
- lock it.
-
- Use HGetState and HSetState to save & restore the "locked" state
- of a handle when you lock it.
-
- 10.3) Q: How do I dispose of Handles?
-
- A: DisposeHandle (formerly called DisposHandle) once and ONLY
- once will do the trick. Trying to dispose of an already disposed
- Handle is an error. DoubleTrouble (see above) will catch such
- bugs when they do occur.
-
- 10.4) Q: What about resources?
-
- A: Calling GetResource returns NULL if the resource is not found
- or there is not enough memory, else it returns a handle to the
- resource. This handle may be moved or locked like any other
- handle, but DO NOT call DisposeHandle to get rid of a resource
- handle - call ReleaseResource. DisposeResource (see above) will
- catch this kind of bug.
-
- Remember that AddResource makes a resource handle out of an
- ordinary handle, and RmveResource or DetachResource makes an
- ordinary handle out of a resource handle. You cannot call
- AddResource with a resource handle; you have to DetachResource
- it first.
-
- Resource handles are automagically disposed when the resource
- file they belong to is closed.
-
- 10.5) Q: I'm trying to use a largish array in Think C, but get a
- "code overflow" error. This is valid C, why doesn't it work?
-
- A: The ANSI standard does not guarantee that any structure
- larger than 32767 bytes be correctly handled. Because of
- historical constraints, the Mac memory model is built around
- several small blocks of size 32K or less; these are used both
- for code and global/static data. If you want to use more code or
- data, you have to turn on "far code" or "far data" - you still
- will not get around the restriction of 32K code or data per
- compiled file, though.
-
- As opposed to, say, DOS or Windows, however, you can allocate as
- much memory as you want (and there is in the machine) and step
- through it using ordinary pointers; it's just that global and
- static data space is addressed off the A5 register using a 16bit
- displacement addressing mode in the 68000 processor.
-
- *11* _Gestalt and compatibility
-
- 11.1) Q: I see all these people call Gestalt without first
- checking whether it's implemented. Isn't that bad?
-
- A: No; Gestalt and a few other traps (the HXxx file manager
- traps, and FindFolder) are implemented using glue so they do the
- right thing even if the trap is not implemented.
-
- If you want to get rid of the glue, you can #define
- SystemSevenOrLater (and, using Think C/C++, re-pre-compile
- MacHeaders) However, then you will be responsible for checking
- for these features before you use them.
-
- 11.2) Q: What more functions are implemented in glue?
-
- A: Wake Up and Smell the Glue! [by Matthias Neeracher]
-
- How often have you wished you could use that cool new ToolBox
- call, but didn't want to make your application System 7
- dependent? Well, it might be that you *could* in fact have used
- the call. Several traps are implemented in glue, that is, much
- of their functionality is linked into your application and thus
- available even if you are running under an old System.
-
- This list applies to MPW 3.2 and should also be valid for the
- current version of Think C. If you find any inaccuracies, please
- report them to me. (neeri@iis.ee.ethz.ch)
-
- FSOpen: Tries first OpenDF, then Open.
-
- HOpenResFile: Full functionality emulated if trap not available
-
- HCreateResFile: Full functionality emulated if trap not
- available
-
- FindFolder: Under System 6, understands the following values for
- folderType and returns the System Folder for all of them:
-
- kAppleMenuFolderType
-
- kControlPanelFolderType
-
- kExtensionFolderType
-
- kPreferencesFolderType
-
- kPrintMonitorDocsFolderType
-
- kStartupFolderType
-
- kSystemFolderType
-
- kTemporaryFolderType
-
- SysEnvirons: Full functionality emulated if trap not available
-
- NewGestalt: Returns an error if not implemented
-
- ReplaceGestalt: Returns an error if not implemented
-
- Gestalt: The following selectors are always implemented:
-
- vers mach sysv proc fpu
-
- qd kbd atlk ram lram
-
- 11.3) Q: I have to support System 6, don't I?
-
- A: It would be foolish to lock yourself out of the many benefits
- the System 7 API provides for software that you start to write
- now. Some of the System 6 and older things (likely SFGetFile and
- wdRefNums among others) will be phased out of the interfaces and
- lose support; especially on future platforms.
-
- The installed base of System 7 is larger than that of System 6;
- this is not surprising because Apple has been shipping System 7
- for several years with all new machines, including the LCII,
- Classic II, Performas and Color Classic. Another argument is
- that newer computer owners (having System 7) are much more
- likely to buy new software than old computer owners who have
- systems that already do what they want them to.
-
- The added work to support both System 6 and System 7 is
- significant; if you have the time and money you may want to do
- it, but only supporting System 6 and not System 7 is doomed to
- fail in the market of today.
-
- Some may call this position subjective; I call it business sense
- based on market demographics. A rule of thumb may be that if you
- target color machines only, you can just as well demand System 7
- as well.
-
- *12* Standalone code and dynamic linking
-
- 12.1) Q: I've got a CODE resource off in limboland (sometimes
- called the resource fork) and I want to open it... what do I do?
- A: You open the file you have the code resource in, load the
- resource and lock it high (don't unlock it first, since someone
- else may be using it). Then you cast the handle to a function
- pointer, and call it normally.
-
- Suppose your code resource is compiled as a SACD id 128, and is
- defined as:
-
- *code*
- long
- main ( MyParams * params ) {
- switch ( params -> message ) {
- case messageInit :
- return init ( params ) ;
- ...
- }
- return 0L ;
- }
- *end*
-
- Also suppose you already have the vRefNum, parID and name of the
- resource file you want to use. Do this:
-
- *code*
- setup_paramblock ( & the_params ) ;
- the_params . message = messageInit ;
- refNum = HOpenResFile ( vRefNum , parID , name , fsRdPerm ) ;
- if ( refNum < 1 ) {
- fail ( ResError ( ) ) ;
- }
- the_code = GetResource ( 'SACD' , 128 ) ;
- HLockHi ( the_code ) ;
- retval = ( * ( ( long ( * ) ( MyParams * ) ) StripAddress ( * the_code ) ) ) ( & the_params ) ;
- ...
- *end*
-
- The StripAddress is important; if your app is running in 24bit
- mode, the resource handle may contain tag bits and you don't
- want strange things to happen if the code resource switches into
- 32bit mode (which QuickDraw may do, incidentally)
-
- Exactly how you structure your calling conventions is up to you;
- there is no accepted standard (except for HyperCard XCMDs, but
- that is probably overkill for you).
-
- *13*
-
- 13.1) Q: How do I read the modifier keys of the keyboard?
-
- A: Just call EventAvail and check the event.modifiers field.
- Only works when you are in the foreground. You can also use
- GetKeys(), or (as a last resort) check the lo-mem global KeyMap
- directly.
-
- 13.2) Q: How do I move the mouse cursor to a specific position?
-
- A: Wait! Don't do it! There has to be a better way!
-
- If you feel you HAVE to do it (for a game or VERY special
- simulation situation) you can use the Cursor Device Manager
- documented in the tech notes on ftp.apple.com. If that
- manager is not installed, as it's not on older Macs, you can
- use the following code:
-
- ----- How to move the mouse (info in C): -----
- you need to have some low-memory globals defined. they may be defined in
- SysEqu.h.
-
- #define MTemp 0x828
- #define RawMouse 0x82c
- #define CrsrNewCouple 0x8ce
-
- note that CrsrNewCouple is actually a combination of two globals, just
- to make our life slightly easier.
-
- the code i use to move the mouse is:
-
- *code*
- void
- MoveMouseTo ( Point where ) {
-
- HideCursor ( ) ;
- * ( Point * ) RawMouse = where ;
- * ( Point * ) MTemp = where ;
- * ( short * ) CrsrNewCouple = -1 ;
- ShowCursor ( ) ;
- }
- *end*
-
- you need to hit a couple more global variables if you want this to
- work properly in a multiple-monitor system, but i forget what they are
- offhand. poke through SysEqu.h, and you should be able to figure it out
- without a problem.
- ----------------------------------------------
-
- On the PowerPC, these lo-mem globals may not be available for
- native applications; however, all Power Macintoshes implement the
- Cursor Device Manager.
-
- There is also a file on nada.kth.se:pub/hacks/mac-faq/MoveMouse.c
- which shows how to use the Cursor Device Manager, written by an
- excellent Apple engineer. Grab!
-
-
- *14* QuickTime
-
- 14.1) Q: I want to write a Amiga QuickTime player and need the
- CODEC format details.
-
- A: Although the structure of QuickTime movies is well documented
- in Inside Mac: QuickTime, the inner workings of the Apple
- compression modules is a trade secret that Apple will only
- license to you at great cost. Perhaps it's time for a freeware,
- cross-platform QuickTime codec?
-
- *15* Windows, Menus and Dialogs
-
- 15.1) Q: My menus don't show up in the menu bar
-
- A: If your menus are hiearchical, you'll have to install them
- manually; GetNewMBar won't do it for you. See also 15.2.
-
- 15.2) Q: When the user selects my menus, I get strange results
- back; they seem to have different menu IDs than my menus?
-
- A: The Menu ID as used by the menu manager is NOT the same
- thing as the MENU resource ID (used in the MBAR resource and
- with GetMenu()) When you create a MENU, ResEdit sets the menu
- ID to the MENU resource ID, but if you re-number the resource,
- you will have to open the menu in ResEdit and change the menu
- ID usiung the "Edit MENU ID" menu item.
-
- 15.3) Q: I use GetMenu() to find a menu in the menu bar, and then
- change it, but it seems I have a memory leak OR my changes
- don't "punch through"
-
- A: GetMenu() is only intended if you don't already have the
- menu "in memory." The call you should use almost all the time
- is GetMHandle() which gets the handle to a menu in the current
- menu bar by its menu ID (not resource id)
-
- *16* Ice Cream and Frozen Yoghurt
-
- 16.1) Q: Dessert?
-
- A: Honey Hill Farms Cookie Jar Frozen Yoghurt or Haagen-Dazs
- Raspberry & Cream Ice Cream.
-
- Hokey-Pokey icecream with chocolate sauce and (for those who
- like their brain food firmer) Almond and Double Chocolate
- CookieTime cookies!? [Denis Birnie]
- --
- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe --
- This signature is kept shorter than 4 lines in the interests of UseNet
- S/N ratio.
-